import os
import asyncio
from multiprocessing import Process
import time
import random
from typing import List,Callable

#------------------------------ 方案一  只能在 unix ---------------------------------------------------

#进程共享
pid_loops ={}

def get_event_loop():
    return pid_loops[os.getpid()]

def asyncio_init():
    pid = os.getpid()
    if pid not in pid_loops:
        pid_loops[pid] = asyncio.new_event_loop()
        #设置 loop 的 pid 为进程ID
        pid_loops[pid].pid = pid

def main_unix():
    #注册 os.fork 执行后的回调函数
    os.register_at_fork(after_in_child=asyncio_init,after_in_parent=asyncio_init)
    if os.fork() == 0:
        #子进程
        loop = get_event_loop()
        print("子进程",loop.pid)
    else:
        loop = get_event_loop()
        print("主进程",loop.pid)


#----------------------------------   跨平台 -------------------------------------------------
processes:List[Process] =[]


def cleanup():
    """
    清理进程，等待进程结束
    """
    global processes
    while processes:
        p = processes.pop()
        try:
            p.join()
        except KeyboardInterrupt as e:
            p.terminate()


async def worker():
    """
    模拟耗时协程任务
    """
    times = random.randint(0,3)
    result =await asyncio.sleep(times,result=f"working in process[{os.getpid()}]")
    print(result)

def process_main(coro_worker: Callable,num_of_coros: int ):
    """
    进程执行函数,使用了比较低级的API,主要用来描述过程内容
    """
    loop = asyncio.new_event_loop()
    try:
        workers = [coro_worker() for _ in range(num_of_coros)]
        #注意这里的 gather 要指定 loop=loop
        loop.run_until_complete(asyncio.gather(*workers,loop=loop))
    except KeyboardInterrupt as e:
        loop.stop()
    finally:
        loop.close()

def process_main_adv(coro_worker: Callable,num_of_coros: int ):
    """
    进程执行函数,直接使用asyncio.run 来避免自己创建 loop
    """
    async def execute():
        workers = [coro_worker() for _ in range(num_of_coros)]
        await asyncio.gather(*workers)
    asyncio.run(execute())

def main(list_process,num_procs,num_coros,proc_main):
    for _ in range(num_procs):
        p = Process(target=proc_main,args=(worker,num_coros))
        list_process.append(p)
        p.start()

if __name__ == '__main__':
    try:
        main(processes,2,2,process_main_adv)
    except KeyboardInterrupt as e:
        print("CTRL+C pressed 中断任务")
    finally:
        cleanup();
        print("cleanup finished")